// VBoost.cpp : Implementation of DLL Exports.


// Note: Proxy/Stub Information
//      To build a separate proxy/stub DLL, 
//      run nmake -f VBoostps.mk in the project directory.

#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "VBoostTypes.h"
#include "VBoostApp.h"

#include "VBoost_i.c"
#include "VBoostTypes_i.c"

static const LPSTR lpszCLSIDKeys[] = {"E2"}; //CLSID_VBoostApp

static const LPSTR lpszProgIDKeys[] = {"VBoost.VBoostApp\\CLSID"};
static char szCLSIDBase[] = "CLSID\\{20708Exx-24E3-11D3-AB5C-D41203C10000}\\InprocServer32";

HINSTANCE g_hinst;
HINSTANCE g_hinstIntl=0;
volatile ULONG g_cObj=0;
volatile ULONG g_cLock=0;

/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point

extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        g_hinst = hInstance;
        DisableThreadLibraryCalls(hInstance);
    }
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE

STDAPI DllCanUnloadNow(void)
{
    return (g_cObj || g_cLock) ? S_FALSE : S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
    CBaseClassFactory *pcf = NULL;
    *ppv = NULL;
    const IID FAR* pIID = NULL;

    if (IsEqualCLSID(rclsid, CLSID_VBoostRootImpl))
    {
        pcf = new CVBoostAppCF;
        pIID = &__uuidof(VBoostRoot);
    }
    else
    {
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    if (!pcf)
    {
        return E_OUTOFMEMORY;
    }

    pcf->m_pIID = pIID;
    pcf->AddRef();
    *ppv = (IClassFactory*)pcf;
    return NOERROR;
}

/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry

STDAPI DllRegisterServer(void)
{
    HRESULT hrLoadTlb;
    char szSysFileName[_MAX_PATH];
    HKEY hkey;
    int i;
    DWORD dwLen = GetModuleFileName(g_hinst, szSysFileName, 256);
    DWORD dwDisposition;
    USES_CONVERSION;

    LPWSTR lpOleFileName = A2W(szSysFileName);
    ITypeLib FAR* ptlib = NULL;
    if (SUCCEEDED(hrLoadTlb = LoadTypeLib(lpOleFileName, &ptlib)))
    {
        hrLoadTlb = RegisterTypeLib(ptlib, lpOleFileName, NULL);
        ptlib->Release();
    }

    for (i = 0; i < DIM(lpszCLSIDKeys); i++)
    {
        memcpy((void*) &szCLSIDBase[13], lpszCLSIDKeys[i], 2 * sizeof(char)); 
        RegCreateKeyEx(HKEY_CLASSES_ROOT,
                 szCLSIDBase, 
             NULL, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
             &hkey, &dwDisposition);
        RegSetValueEx(hkey, NULL, NULL, REG_SZ, (const unsigned char *) szSysFileName, dwLen + 1);
        RegSetValueEx(hkey, "ThreadingModel", NULL, REG_SZ, (const unsigned char *) "Apartment", 39);
        // UNDONE: Add ProgID value?
        RegCloseKey(hkey);
    }

    //Register ProgID's
    szCLSIDBase[44] = 0; //Insert NULL termination
    for (i = 0; i < DIM(lpszProgIDKeys); i++)
    {
        memcpy((void*) &szCLSIDBase[13], lpszCLSIDKeys[i], 2 * sizeof(char)); 
        RegCreateKeyEx(HKEY_CLASSES_ROOT,
                 lpszProgIDKeys[i] , 
             NULL, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
             &hkey, &dwDisposition);
        RegSetValueEx(hkey, NULL, NULL, REG_SZ, (const unsigned char *) szCLSIDBase + 6, 39);
        RegCloseKey(hkey);
    }
    return hrLoadTlb;
}

/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
    UnRegisterTypeLib(LIBID_VBoost6, 1, 0, 0, SYS_WIN32);
    int i;

    for (i = 0; i < DIM(lpszCLSIDKeys); i++)
    {
        memcpy((void*) &szCLSIDBase[13], lpszCLSIDKeys[i], 2 * sizeof(char)); 
        RegDeleteKey(HKEY_CLASSES_ROOT, szCLSIDBase);
        szCLSIDBase[44] = 0;
        RegDeleteKey(HKEY_CLASSES_ROOT, szCLSIDBase);
        szCLSIDBase[44] = '\\';
    }

    char szSimpleKey[25];
    int len;
    for (i = 0; i < DIM(lpszProgIDKeys); i++)
    {
        RegDeleteKey(HKEY_CLASSES_ROOT, lpszProgIDKeys[i]);
        len = lstrlen(lpszProgIDKeys[i]) - 6;
        memcpy((void*) szSimpleKey, lpszProgIDKeys[i], len);
        szSimpleKey[len] = 0;
        RegDeleteKey(HKEY_CLASSES_ROOT, szSimpleKey);
    }
    return NOERROR;
}
